JSON and serialization
# What is JSON?
JSON (JavaScript Object Notation) is a way to write data in JavaScript. Like XML, it allows to
encode structured data in a text format that can be easily read by humans. Its simple syntax
and native compatibility with JavaScript have made it a widely used format.
Data types that can be encoded are JavaScript types (see the `serde_json:Value` enum for more
details):
* `Bool`: equivalent to rust's `bool`
* `I64`: equivalent to rust's `i64`
* `U64`: equivalent to rust's `u64`
* `F64`: equivalent to rust's `f64`
* `String`: equivalent to rust's `String`
* `Array`: equivalent to rust's `Vec`, but also allowing objects of different types in the
same array
* `Object`: equivalent to rust's `BTreeMap`; set the
`preserve_order` feature to use `LinkedHashMap` instead
* `Null`
An object is a series of string keys mapping to values, in `"key": value` format. Arrays are
enclosed in square brackets ([ ... ]) and objects in curly brackets ({ ... }). A simple JSON
document encoding a person, his/her age, address and phone numbers could look like
```ignore
{
"FirstName": "John",
"LastName": "Doe",
"Age": 43,
"Address": {
"Street": "Downing Street 10",
"City": "London",
"Country": "Great Britain"
},
"PhoneNumbers": [
"+44 1234567",
"+44 2345678"
]
}
```
If we assume that `FirstName` is optional and all other fields are mandatory, the above JSON could
correspond to the following Rust structs:
```ignore
#[derive(Serialize, Deserialize)]
struct Data {
#[serde(rename="FirstName")] // to comply with Rust coding standards
first_name: Option,
LastName: String,
Age: u32,
Address: Address,
PhoneNumbers: Vec,
}
#[derive(Serialize, Deserialize)]
struct Address {
Street: String,
City: String,
Country: String,
}
```
# Type-based Serialization and Deserialization
Serde provides a mechanism for low boilerplate serialization & deserialization of values to and
from JSON via the serialization API. To be able to serialize a piece of data, it must implement
the `serde::Serialize` trait. To be able to deserialize a piece of data, it must implement the
`serde::Deserialize` trait. Serde provides provides an annotation to automatically generate
the code for these traits: `#[derive(Serialize, Deserialize)]`.
The JSON API also provides an enum `serde_json::Value` and a method `to_value` to serialize
objects. A `serde_json::Value` value can be serialized as a string or buffer using the
functions described above. You can also use the `json::Serializer` object, which implements the
`Serializer` trait.
# Examples of use
## Parsing a `str` to `Value` and reading the result
```rust
extern crate serde_json;
use serde_json::Value;
fn main() {
let data: Value = serde_json::from_str("{\"foo\": 13, \"bar\": \"baz\"}").unwrap();
println!("data: {:?}", data);
// data: {"bar":"baz","foo":13}
println!("object? {}", data.is_object());
// object? true
let obj = data.as_object().unwrap();
let foo = obj.get("foo").unwrap();
println!("array? {:?}", foo.as_array());
// array? None
println!("u64? {:?}", foo.as_u64());
// u64? Some(13u64)
for (key, value) in obj.iter() {
println!("{}: {}", key, match *value {
Value::U64(v) => format!("{} (u64)", v),
Value::String(ref v) => format!("{} (string)", v),
_ => format!("other")
});
}
// bar: baz (string)
// foo: 13 (u64)
}
```